<script setup>
import { Plus } from '@element-plus/icons-vue'
import { onMounted, computed, ref, nextTick } from 'vue';
import replyMessage from './replyMessage.vue';
import { useUserStore } from '@/store/user';
import { ElMessage, ElMessageBox } from 'element-plus';
import { deleteCommentApi } from '@/apis/comment'
import { getAdditionalCommentListApi } from '@/apis/additionalComment'
import { reportApi } from '@/apis/report'
import { addAdditionalCommentApi } from '@/apis/additionalComment'
import { useRouter, useRoute } from 'vue-router';
import { giveUserNameGetUserIdApi } from "@/apis/mention";

const router = useRouter();
const route = useRoute();

const props = defineProps({
  commentData: {
    type: Object,
    required: true
  },
  //手机端点击内容时触发底部回复框方法
  clickMessage: {
    type: Function,
    required: true
  },

  getCommentList: {
    type: Function,
    required: true

  },
  getPostDetail: {
    type: Function,
    required: true
  },
  /* 手机端删除评论 */
  phoneDeleteComment: {
    type: Function,
  }

})



const useStore = useUserStore();

/* 获得token */
const token = computed(() => {
  return useStore.token
})




// #region 举报弹窗代码
// 举报弹窗的输入框
const reportContent = ref('')
// 控制举报弹窗的实现与隐藏
const dialogVisible = ref(false)
// 举报弹窗的多选框数组
const checkList = ref([])

// 上传图片的列表
const fileList = ref([])


// 查看图片的方法
const pictureDialogVisible = ref(false)
const pictureUrl = ref('')
const handlePictureCardPreview = (file) => {
  pictureDialogVisible.value = true
  pictureUrl.value = file.url
}


//删除方法
const handleRemove = (file) => {

  const index = fileList.value.indexOf(file);
  if (index !== -1) {
    fileList.value.splice(index, 1);
  }

  //调用删除图片的接口，直接去数据库将这个url删掉即可
}


// 上传图片成功的方法
const handleSuccess = (res, file, fileList) => {

  //成功方法会把展示的file数据和后台返回的数据都拿到
  file.url = res.data
  try {
    fileList.value.push(file)

  } catch (error) {
    // console.log(error)
  }
}




//上传图片时的检查
const handleBeforeUpload = (file) => {
  if (file.type !== 'image/gif' && file.type !== 'image/jpg' && file.type !== 'image/jpeg' && file.type !== 'image/png') {
    ElMessage.error('请上传jpg/jpeg/png/gif格式图片!')
    return false
  } else if (file.size / 1024 / 1024 > 3) {
    ElMessage.error('图片超过3MB!')
    return false
  }

}


/* 将图片对象转为字符串数组 */
const fileListString = computed(() => {
  return fileList.value.map((file) => file.url)
})


// 举报弹窗提交
const submit = async () => {

  /* 举报原因不能为空 */
  if (checkList.value.length === 0) {
    ElMessage.error('请选择举报原因!')
    return
  }

  // 调用举报接口
  const ref = await reportApi({
    userId: useStore.userInfo.id,
    commentId: props.commentData.commentId,
    reason: checkList.value.toString(),
    content: reportContent.value,
    pictures: fileListString.value
  })
  ElMessage.success(ref.data)

  //清理数据并关闭举报弹窗
  checkList.value = []
  reportContent.value = ''
  fileList.value = []
  dialogVisible.value = false
}




// #endregion


// #region 删除评论
const deleteComment = async () => {
  // ElMessageBox
  ElMessageBox.confirm('确定删除该评论吗？删除评论会将该评论及其所有追评一起删除', '提示',).then(async () => {
    const ref = await deleteCommentApi({
      commentId: props.commentData.commentId,
    })
    ElMessage.success(ref.data)

    /* 手机端不需要更新列表数据，因为整个数组都是push的 */
    if (window.innerWidth > 768) {
      // 电脑端就再次获得列表数据
      await props.getCommentList(undefined, sessionStorage.getItem('currentPage'))
    } else {
      /* 手机端需要将这个把评论的id从数组中删除掉。后端已经删除了，这里只需要更新列表数据 */
      /* 传给父类，让父类更新列表数据 */
      props.phoneDeleteComment(props.commentData.commentId)
    }

    // 再次获得帖子详情
    props.getPostDetail()
  }).catch(() => {
    ElMessage.info('取消删除')
  })



}
// #endregion




// #region 回复评论

//追评时也需要将父组件的高度更新。
//具体做法是子组件触发父组件的函数。函数就动态的添加或删除一个固定的值
const addAdditionalCommentReplyHeight = () => {
  dynamicHeight.value.style.height = (dynamicHeight.value.offsetHeight + 130 + 'px');
}

const reduceAdditionalCommentReplyHeight = () => {

  dynamicHeight.value.style.height = (dynamicHeight.value.offsetHeight - 130 + 'px');
}


// 增加追评修改父组件的高度
const submitAfterHeight = () => {

  if ((currentPage.value * 5) >= additionalCommentList.value.total) {
    /* 说明在最后一页，更新高度 */
    /* 通过类名获取高度 */
    const lastReplyMessage = document.querySelector(`.${lastReplyClass}`)


    dynamicHeight.value.style.height = dynamicHeight.value.offsetHeight - (130 - lastReplyMessage.offsetHeight) + 'px'
  } else {
    /* 说明不在最后一页，直接减去130px的回复框高度 */
    dynamicHeight.value.style.height = dynamicHeight.value.offsetHeight - 130 + 'px'
  }



}


/* 删除追评后更新父组件高度 */
const deleteAfterHeight = (height) => {

  if (additionalCommentList.value.records.length === 1) {

    /* 说明没有追评了，恢复到没有任何追评的高度 */
    dynamicHeightJudge()
    /* 将additionalCommentList的total设置为0，下次点击回复时就会出现回复框 */
    additionalCommentList.value.total = 0;
  }

  /* 判断是否在最后一页 */
  if ((currentPage.value * 5) >= additionalCommentList.value.total) {
    /* 说明在最后一页，更新高度 */
    dynamicHeight.value.style.height = (dynamicHeight.value.offsetHeight - height) + 'px';
  } else {
    /* 说明不在最后一页 */
    dynamicHeight.value.style.height = 'auto';
  }


}


const additionalCommentReplyHeight = { addAdditionalCommentReplyHeight, reduceAdditionalCommentReplyHeight, submitAfterHeight, deleteAfterHeight }

// 定义类名变量
const lastReplyClass = `last-reply-${props.commentData.commentId}`;


// 动态类名函数
const getCommentLastReplyClass = (index) => {
  return {
    [lastReplyClass]: index === additionalCommentList.value.records.length - 1,
  };
};



// #endregion


//#region 动态获取追评论区高度
const replyContainer = ref(null)
const dynamicHeight = ref(null);
const isReply = ref(false);
const is = ref(true);
// 无追评时的回复框
const textarea = ref('')

//显示追评时动态更新div高度核心代码
function toggleReply() {


  //手机端和电脑端需要两套不同的实现
  // 电脑端实现
  if (window.innerWidth > 768) {
    // 没有追评时才显示回复框
    if (additionalCommentList.value.total === 0) {

      // 更新父容器高度
      if (is.value) {
        dynamicHeight.value.style.height = dynamicHeight.value.offsetHeight + 125 + 'px';
        is.value = false;
        //定时器解决快速点击元素造成的高度不一致问题
        isReply.value = true;
        setTimeout(() => {
          isReply.value = false;
        }, 300)

      } else {
        dynamicHeight.value.style.height = dynamicHeight.value.offsetHeight - 125 + 'px';
        is.value = true;

        isReply.value = true;
        setTimeout(() => {
          isReply.value = false;
        }, 300)
      }

    } else {
      // 有追评时显示追评
      // 更新父容器高度
      if (is.value) {


        // 核心是盒子总高度 = 盒子高度 + 追评高度 + 50px(分页器)
        dynamicHeight.value.style.height = dynamicHeight.value.offsetHeight + replyContainer.value.offsetHeight + 50 + 'px';
        is.value = false;
        //定时器解决快速点击元素造成的高度不一致问题
        isReply.value = true;
        setTimeout(() => {
          isReply.value = false;
        }, 300)

      } else {


        /* 给定这个组件的高度 */
        dynamicHeightJudge()


        is.value = true;

        isReply.value = true;
        setTimeout(() => {
          isReply.value = false;
        }, 300)
      }
    }
  } else {
    //手机端实现。手机端不需要考虑没有回复这种情况
    // 更新父容器高度
    if (is.value) {

      /* 更新高度 */
      dynamicHeight.value.style.height = dynamicHeight.value.offsetHeight + replyContainer.value.offsetHeight + 35 + 'px';

      is.value = false;
      //定时器解决快速点击元素造成的高度不一致问题
      isReply.value = true;
      setTimeout(() => {
        isReply.value = false;
      }, 300)

    } else {
      // setTimeout(() => {
      //   dynamicHeight.value.style.height = dynamicHeight.value.offsetHeight - replyContainer.value.offsetHeight - 35 + 'px';
      // }, 100)

      /* 给定这个组件的高度 */
      dynamicHeightJudge()

      is.value = true;

      isReply.value = true;
      setTimeout(() => {
        isReply.value = false;
      }, 300)
    }
  }


}

// #endregion

// #region 适配双端的动态宽度计算属性


// 动态计算内容区域宽度:span
const dynamicContent = computed(() => {
  return window.innerWidth > 768 ? 19 : 24;
})

// 动态计算头像区域宽度:span
const dynamicAvatar = computed(() => {
  return window.innerWidth > 768 ? 4 : 24;
})

// 动态计算头像大小
const avatarWidth = computed(() => {
  return window.innerWidth > 768 ? 100 : 30;
})

//动态计算举报宽度
const reportWidth = computed(() => {
  return window.innerWidth > 768 ? '500px' : '100vw';
})
// #endregion


// #region 获取数据区

// 获取该评论的追评submitAfterHeight
const additionalCommentList = ref([])
const getAdditionalCommentList = async () => {


  const ref = await getAdditionalCommentListApi({
    currentPage: currentPage.value,
    commentId: props.commentData.commentId,
  })

  additionalCommentList.value = ref

  // 给每个评论添加commentId
  additionalCommentList.value.records.forEach((item) => {
    item.commentId = props.commentData.commentId
  })

}




// 内容区ref
const messageHeight = ref(null)

onMounted(async () => {

  setTimeout(() => {
    /* 给定这个组件的高度 */
    dynamicHeightJudge()

  }, 300)

  // 获得追评数据
  await getAdditionalCommentList()

})


/* 楼层高度判断方法 */
const dynamicHeightJudge = () => {
  //整个大div的高度,小于300就给个固定高度
  setTimeout(() => {


    if (messageHeight.value.offsetHeight < 300) {
      //还要考虑手机端和pc端给个固定高度是不一致的
      if (window.innerWidth > 768) {
        dynamicHeight.value.style.height = '300px'
        messageHeight.value.style.height = '278px'
      } else {
        dynamicHeight.value.style.height = '150px'
        messageHeight.value.style.height = '80px'
      }
    } else {
      // 内容区高度大于300，动态计算父容器高度
      // 电脑端
      if (window.innerWidth > 768) {
        dynamicHeight.value.style.height = messageHeight.value.offsetHeight + 22 + 'px';

      } else {
        dynamicHeight.value.style.height = messageHeight.value.offsetHeight + 70 + 'px';
      }
    }

  }, 100)
}

// #endregion


// #region 无回复时的追评方法

const addAdditionalComment = async () => {
  // console.log(textarea.value);
  if (textarea.value.trim() === '') {
    ElMessage.error('请输入回复内容!')
    return
  }

  const ref = await addAdditionalCommentApi({
    content: textarea.value,
    commentId: props.commentData.commentId,
    userId: useStore.userInfo.id,
    beCommentUserId: props.commentData.userId
  })

  ElMessage.success(ref.data)

  // 再次获得列表数据
  await props.getCommentList()

  /* 获得该评论的追评 */
  getAdditionalCommentList()

  // 重置textarea
  textarea.value = ''

  // 关闭回复框
  toggleReply()
}


// #endregion


// #region 分页代码
const currentPage = ref(1)

const handleChange = async () => {
  await getAdditionalCommentList()


  /* 让组件高度auto */
  dynamicHeight.value.style.height = 'auto';
}
// #endregion


// #region 跳转到用户页
const toUserPage = () => {

  router.push(`/user/${props.commentData.userId}`)
}
// #endregion



// // #region 回复层主
// const handleReplyCengZhu = () => {

//   console.log(additionalCommentList.value.total);

//   additionalCommentList.value.total = 0

//   // 打开回复框
//   toggleReply()
// }

// // #endregion


// #region 格式化评论内容
const formatContent = function (content) {
  return content
    .replace(/\n/g, '<br>')
    .replace(/ {2,}/g, (match) => '&nbsp;'.repeat(match.length))
    .replace(/@(\S+?)(?=\s|$)/g, (match) =>
      `<span style="color: #1890ff; cursor: pointer;">${match}</span>`
    );
}

const handleContentClick = async (event) => {
  props.clickMessage(event, props.commentData.content, props.commentData.commentId, props.commentData.userId, getAdditionalCommentList)
  const target = event.target;

  if (target.tagName === 'SPAN') {
    const name = target.innerText;

    // 调用接口获取用户id
    /* 发送请求去后端，查询有没有这个用户，如果有就跳转到用户页，如果没有就提示用户不存在 */
    try {
      const res = await giveUserNameGetUserIdApi(name);
      router.push(`/user/${res.data}`);
    } catch (error) {

    }

  }
}

// #endregion


// 暴露给父组件的方法
defineExpose({
  getAdditionalCommentList,
})
</script>

<template>
  <div class="message" ref="dynamicHeight">
    <el-row>
      <!-- 左侧用户信息栏 hidden-md-and-down -->
      <el-col :span=avatarWidth class="user-info">
        <el-avatar class="avatar" shape="square" :size=avatarWidth fit="fill" :src="commentData.avatar" />

        <div class="name" @click="toUserPage"><span>{{ commentData.userName }}</span></div>
        <div class="level">
          <span>{{ commentData.chenghao }} </span>
          <svg-icon :name="commentData.icon" color="blue" />
        </div>

      </el-col>

      <!-- 右侧发言信息 -->
      <el-col :span="dynamicContent">


        <div ref="messageHeight" class="content">
          <div v-html="formatContent(commentData.content)" @click="handleContentClick($event)">
          </div>

          <div v-if="commentData.imgList !== null" class="pictures">
            <el-image v-for="(item, index) in commentData.imgList" :key="index" :src="item" :preview-src-list="[item]"
              :fit="cover" style="margin-right: 10px;" hide-on-click-modal="true" />
            <!-- <img :src="commentData.imgList[0]" alt=""> -->
          </div>
        </div>



        <!-- 底部信息 -->
        <div class="content-info">
          <a class="need-left-margin blue"></a>
          <!-- 不是自己的评论才能举报 -->
          <a v-if="commentData.userId !== useStore.userInfo.id" class="need-left-margin blue"
            @click="dialogVisible = true">举报</a>
          <span class="need-left-margin gray">{{ commentData.floor }}楼</span>
          <span class="need-left-margin gray">{{ commentData.commentTime }}</span>
          <button class="need-left-margin blue" @click="toggleReply" :disabled="isReply">回复({{
            additionalCommentList.total }})</button>
          <!-- <button class="need-left-margin blue" v-if="additionalCommentList.total !== 0"
            @click="handleReplyCengZhu">回复层主</button> -->
          <button @click="deleteComment" class="need-left-margin blue"
            v-if="commentData.userId === useStore.userInfo.id">删除</button>
        </div>

        <!-- 无回复时结构 调用这个组件的时候需要判断当前有没有回复.如果没有回复就用这个.有就用下面的 -->
        <div class="empty-reply hidden-md-and-down" v-if="additionalCommentList.total === 0">
          <el-input v-model="textarea" resize="none" class="report" :rows="2" style="width: 80%; margin :10px 0 0 80px;"
            type="textarea" placeholder="恶言伤人心思密达！" maxlength="150" show-word-limit
            @keyup.enter="addAdditionalComment" />
          <br>
          <el-button type="primary" class="published" @click="addAdditionalComment">发表</el-button>
        </div>

        <!-- 有回复时结构 -->
        <div class="have-reply" ref="replyContainer" v-else>
          <replyMessage v-for="(item, index) in additionalCommentList.records" :key="item.additionalCommentId"
            :additionalCommentList="item" :parentHeight="additionalCommentReplyHeight"
            :getAdditionalCommentList="getAdditionalCommentList" :class="getCommentLastReplyClass(index)"
            :id="`reply-${item.additionalCommentId}`" :clickReplyMessage="clickMessage">
          </replyMessage>

          <!-- :class="getFloorClass(index)" -->

          <!-- 分页 -->
          <el-pagination v-model:current-page="currentPage" @change="handleChange" class="pagination" background
            layout="prev, pager, next" :total="additionalCommentList.total" :default-page-size="5" />
        </div>
      </el-col>
    </el-row>



    <!-- 举报弹窗 -->
    <el-dialog v-model="dialogVisible" title="举报内容" :width=reportWidth :before-close="handleClose">
      <!-- 举报原因 -->
      <span class="report-title">请选择举报原因（必填）</span>
      <div class="report">

        <el-checkbox-group v-model="checkList" :max="3">
          <el-checkbox value="色情低俗" label="色情低俗" size="large" />
          <el-checkbox value="垃圾广告" label="垃圾广告" size="large" />
          <el-checkbox value="辱骂攻击" label="辱骂攻击" size="large" />
          <el-checkbox value="违法犯罪" label="违法犯罪" size="large" />
          <el-checkbox value="时政不实信息" label="时政不实信息" size="large" />
          <el-checkbox value="青少年不宜" label="青少年不宜" size="large" />
          <el-checkbox value="侵犯权益" label="侵犯权益" size="large" />
          <el-checkbox value="其他" label="其他" size="large" />
        </el-checkbox-group>
      </div>

      <!-- 举报内容补充 -->
      <div>
        <p class="report-title">详细信息（选填）</p>
        <el-input v-model="reportContent" class="report" style="width: 100%" :rows="3" type="textarea"
          placeholder="提供更多信息有助于举报被快速处理哦" maxlength="100" show-word-limit />
      </div>

      <!-- 举报图片上传 -->
      <div>
        <p class="report-title">图片上传（选填）</p>

        <el-upload action="http://8.134.78.60:8080/user/common/upload" :headers="{ token }" name="file"
          list-type="picture-card" :auto-upload="true" :before-upload="handleBeforeUpload" :on-success="handleSuccess"
          v-model:file-list="fileList">
          <el-icon>
            <Plus />
          </el-icon>

          <template #file="{ file }">
            <div>
              <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />
              <span class="el-upload-list__item-actions">

                <span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
                  <el-icon><zoom-in /></el-icon>
                </span>


                <span v-if="!disabled" class="el-upload-list__item-delete" @click="handleRemove(file)">
                  <el-icon>
                    <Delete />
                  </el-icon>
                </span>
              </span>
            </div>
          </template>


        </el-upload>

        <el-dialog v-model="pictureDialogVisible">
          <img w-full :src="pictureUrl" alt="找不到" />
        </el-dialog>

      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submit">
            提交
          </el-button>
        </div>
      </template>

    </el-dialog>

  </div>

</template>

<style lang='scss' scoped>
.pagination {
  // margin-top: 20px;
  float: right;
  margin-top: 10px;
}

//电脑端样式
@media (min-width: 992px) {


  .message {
    margin: 0 auto;
    width: $base-container-width;
    position: relative;
    margin-top: 20px;
    border-bottom: 1px solid rgb(148, 148, 148);
    border-top: 1px solid rgb(148, 148, 148);
    overflow: hidden;
    transition: height 0.5s ease;


    .user-info {
      padding: 40px;
      text-align: center;
      height: 100px;
    }

    .name {
      color: rgb(12, 84, 113);
      margin: 10px 0;

      & :hover {
        cursor: pointer;
        /* 下划线 */
        text-decoration: underline;
      }
    }

    .level {
      border: 1px solid rgb(126, 127, 128);
      height: 30px;
      display: flex;
      justify-content: space-around;
      align-items: center;
    }

    .content {
      padding-top: 40px;
      //强制中断换行
      word-break: break-all;
      // border: 1px solid red;
      padding-bottom: 20px;


    }

    .content-info {
      text-align: end;
      margin-bottom: 10px;

      .need-left-margin {
        margin-left: 20px;
      }

      .gray {
        color: gray;
      }

      .blue {
        color: rgb(16, 132, 177)
      }
    }

    .report-title {
      margin-bottom: 10px;
      font-size: 15px;
      font-weight: bold;
    }

    .report {
      margin-bottom: 20px;
    }



    //回复结构
    .empty-reply {
      width: 79%;
      height: 115px;
      background-color: rgb(228, 227, 227);
      position: absolute;
      bottom: -100px;
      margin: -15px auto;

      .published {
        position: absolute;
        right: 140px;
        bottom: 10px;
        // margin-left: 810px;
        // margin-top: 10px;

      }
    }

    //有回复时单独结构
    .have-reply {

      margin: 0 auto;
      width: 100%;
      // border: 1px solid red;
      background-color: rgb(247, 248, 250);
    }



  }

  .reply-active {
    border: 1px solid red;
    color: red;
    pointer-events: none;
  }

}

//移动端样式
@media (max-width: 991px) {
  .message {
    width: 100vw;
    position: relative;
    border-bottom: 1px solid rgb(148, 148, 148);
    overflow: hidden;
    transition: height 0.5s ease;
    font-size: 1.8rem;

    .user-info {
      height: 30px;
      padding-left: 10px;
      display: flex;
      justify-content: start;
      align-items: center;
      margin-top: 20px;

      .name {
        margin: 0 10px;

      }

      .level {
        border: 1px solid rgb(126, 127, 128);
        width: 90px;
        display: flex;
        justify-content: space-around;
        align-items: center;
      }
    }

    .content {
      padding: 10px 10px;
      //强制中断换行
      word-break: break-all;
      // border: 1px solid red;
    }

    .content-info {
      text-align: end;
      margin-right: 10px;
      font-size: 1.5rem;

      .need-left-margin {
        margin-left: 20px;
      }

      .gray {
        color: gray;
      }

      .blue {
        color: rgb(16, 132, 177)
      }
    }

    .report-title {
      margin-bottom: 10px;
      font-size: 15px;
      font-weight: bold;
    }

    .report {
      margin-bottom: 20px;
    }



    //有回复时单独结构
    .have-reply {
      padding: 10px;
      margin: 0 auto;
      width: 90%;
      // border: 1px solid red;
      background-color: rgb(247, 248, 250);
    }



  }


}
</style>